﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DbSharp.Framework.TestEngine
{
    public class TestReport
    {
        private List<UnitTestRunner> m_ListUnitTestCase = new List<UnitTestRunner>();
        private List<PerfTestRunner> m_ListPerfTestCase = new List<PerfTestRunner>();

        private void Reset()
        {
            m_ListUnitTestCase.Clear();
            Unit_FailedCount = 0;
            Unit_SuccessfulCount = 0;
            Unit_UncertainCount = 0;

            m_ListPerfTestCase.Clear();
            Perf_FailedCount = 0;
            Perf_SuccessfulCount = 0;
            Perf_UncertainCount = 0;
        }

        private void EndUnitTestCase(UnitTestRunner testRunner)
        {
            m_ListUnitTestCase.Add(testRunner);
            switch (testRunner.CaseExecuteResult.TestState)
            {
                case CaseTestState.NotRun:
                    break;
                case CaseTestState.Successful:
                    Unit_SuccessfulCount++;
                    break;
                case CaseTestState.Failed:
                    Unit_FailedCount++;
                    break;
                case CaseTestState.Uncertain:
                    Unit_UncertainCount++;
                    break;
                default:
                    break;
            }
        }

        private void EndPerfTestCase(PerfTestRunner testRunner)
        {
            m_ListPerfTestCase.Add(testRunner);
            switch (testRunner.CaseExecuteResult.TestState)
            {
                case CaseTestState.NotRun:
                    break;
                case CaseTestState.Successful:
                    Perf_SuccessfulCount++;
                    break;
                case CaseTestState.Failed:
                    Perf_FailedCount++;
                    break;
                case CaseTestState.Uncertain:
                    Perf_UncertainCount++;
                    break;
                default:
                    break;
            }
        }


        private string GetTestSummary(bool displayDetail)
        {
            if ((m_ListPerfTestCase.Count == 0) && (m_ListUnitTestCase.Count == 0))
                return string.Empty;

            StringBuilder sb = new StringBuilder();

            #region Output statistics

            sb.AppendLine("===================");
            sb.AppendLine("Test statistics:");
            sb.AppendLine("===================");
            sb.AppendFormat("  Start time: {0}", StartTime.ToLocalTime());
            sb.AppendLine();
            sb.AppendFormat("  End time: {0}", StartTime.ToLocalTime());
            sb.AppendLine();
            sb.AppendFormat("  Duration: {0}", Duration.ToString());
            sb.AppendLine();

            if (m_ListPerfTestCase.Count > 0)
            {
                sb.AppendFormat("  Perf test results: {0} run ({1} passed, {2} failed, {3} uncertain)", m_ListPerfTestCase.Count, Perf_SuccessfulCount, Perf_FailedCount, Perf_UncertainCount);
                sb.AppendLine();
            }

            if (m_ListUnitTestCase.Count > 0)
            {
                sb.AppendFormat("  Unit test results: {0} run ({1} passed, {2} failed, {3} uncertain)", m_ListUnitTestCase.Count, Unit_SuccessfulCount, Unit_FailedCount, Unit_UncertainCount);
                sb.AppendLine();
            }

            #endregion

            #region Output Perf test detail

            if ((displayDetail) && (m_ListPerfTestCase.Count > 0))
            {
                sb.AppendLine();
                sb.AppendLine("===================");
                sb.AppendLine("Perf test detail:");
                sb.AppendLine("===================");
                foreach (var testRunner in m_ListPerfTestCase)
                {
                    if (testRunner is PerfTestRunner)
                    {
                        sb.AppendLine("  " + testRunner.CaseExecuteResult.ToShortString());
                    }
                }
            }

            #endregion

            #region Output Unit test detail
            if ((displayDetail) && (m_ListUnitTestCase.Count > 0))
            {
                sb.AppendLine();
                sb.AppendLine("===================");
                sb.AppendLine("Unit test detail:");
                sb.AppendLine("===================");
                foreach (var testRunner in m_ListUnitTestCase)
                {
                    if (testRunner is UnitTestRunner)
                    {
                        sb.AppendLine("  " + testRunner.CaseExecuteResult.ToShortString());
                    }
                }
            }
            #endregion

            return sb.ToString();
        }



        public DateTime StartTime { get; set; }
        public DateTime EndTime { get; set; }
        public TimeSpan Duration
        {
            get { return EndTime - StartTime; }
        }

        public int Unit_FailedCount { get; set; }
        public int Unit_SuccessfulCount { get; set; }
        public int Unit_UncertainCount { get; set; }
        public int Perf_FailedCount { get; set; }
        public int Perf_SuccessfulCount { get; set; }
        public int Perf_UncertainCount { get; set; }

        public void BeginReport()
        {
            Reset();
            StartTime = DateTime.Now;
        }

        public void EndReport()
        {
            EndTime = DateTime.Now;
        }


        public void EndTestCase(TestRunnerBase testRunner)
        {
            if (testRunner is UnitTestRunner)
                EndUnitTestCase((UnitTestRunner)testRunner);
            else
                EndPerfTestCase((PerfTestRunner)testRunner);
        }



        public string ToLongString()
        {
            bool displayDetail = true;
            return GetTestSummary(displayDetail);
        }

        public override string ToString()
        {

            bool displayDetail = false;
            return GetTestSummary(displayDetail);
        }

        public CaseTestState GetPerfTestsOverallTestState()
        {
            CaseTestState result = CaseTestState.NotRun;
            if (Perf_FailedCount > 0)
            {
                result = CaseTestState.Failed;
            }
            else if (Perf_UncertainCount > 0)
            {
                result = CaseTestState.Uncertain;
            }
            else if (m_ListPerfTestCase.Count > 0)
            {
                result = CaseTestState.Successful;
            }
            return result;
        }

        public CaseTestState GetUnitTestsOverallTestState()
        {
            CaseTestState result = CaseTestState.NotRun;
            if (Unit_FailedCount > 0)
            {
                result = CaseTestState.Failed;
            }
            else if (Unit_UncertainCount > 0)
            {
                result = CaseTestState.Uncertain;
            }
            else if (m_ListUnitTestCase.Count > 0)
            {
                result = CaseTestState.Successful;
            }
            return result;
        }


    }

}
